﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Runtime.InteropServices;

namespace Douban.Core.Interop
{
    public delegate bool KeyHandler(KeyboardHookStruct khs);

    public class KeyHook
    {
        private IntPtr _hookHandle;
        private KeyHandler _handler;
        private GCHandle _gcHandle;

        public KeyHook(KeyHandler handler)
        {
            if (handler == null) throw new ArgumentNullException("handler");

            _handler = handler;
            WindowsHookProc hookProc = new WindowsHookProc(KeyboardProc);
            _gcHandle = GCHandle.Alloc(hookProc);
            _hookHandle =
                WindowsHookHelper.RegisterWindowsHook(WindowsHookTypes.WH_KEYBOARD_LL, hookProc);
        }

        public void Unload()
        {
            WindowsHookHelper.UnregisterWindowsHook(_hookHandle);
            _gcHandle.Free();
        }

        private int KeyboardProc(int code, int wParam, IntPtr lParam)
        {
            if (code < 0) return WindowsHookHelper.CallNextHook(_hookHandle, code, wParam, lParam);

            KeyboardHookStruct hookStruct = 
                (KeyboardHookStruct)Marshal.PtrToStructure(lParam, typeof(KeyboardHookStruct));

            if (!_handler(hookStruct)) return WindowsHookHelper.CallNextHook(_hookHandle, code, wParam, lParam);

            return 1;
        }
    }
}
